/*
 * @Descripttion:
 * @Author: ziwei
 * @Date: 2022-09-09 16:17:40
 * @LastEditors: ziwei
 * @LastEditTime: 2022-09-13 22:56:34
 */
// 解决循环引用问题，我们可以额外开辟一个存储空间，
// 来存储当前对象和拷贝对象的对应关系，当需要拷贝当前对象时，
// 先去存储空间中找，有没有拷贝过这个对象，如果有的话直接返回，
// 如果没有的话继续拷贝，这样就巧妙化解的循环引用的问题。
//工具方法判断是否是原始了警
// function isObject(target){
//     const type = typeof target
//     return target!=null && (type=='object'||type=='function')
// }
// function deepClone(target, map = new WeakMap()) {
//     if(!isObject(data)){
//         return target
//     }
//     //对象
//     let cloneTarget = Array.isArray(target) ? [] : {};
//     if (map.get(target)) {
//       return map.get(target);
//     } else {
//         console.log("++cloneTarget",target,cloneTarget)
//       map.set(target, cloneTarget);
//     }
//     for (let i in target) {
//       cloneTarget[i] = deepClone(target[i], map);
//     }
//     return cloneTarget;
// }
//可继续遍历的数据类型
const mapTag = '[object Map]'
const setTag = '[object Set]'
const arrayTag = '[object Array]'
const objectTag = '[object Array]'
const argstag = '[object Array]'
//不可继续遍历的数据类型
const boolTag = '[object Boolean]'
const dateTag = '[object Date]'
const numbertag = '[object Number]'
const stringTag = '[object String]'
const symbolTag = '[object Symbol]'
const errorTag = '[object Error]'
const regexTag = '[object RegExp]'
const funcTag = '[object Function]'

const deepTag = [mapTag,setTag,arrayTag,objectTag,argstag]

//工具函数_通用while循环,while的性能好于for in
function forEach(array,interatee){
  let index = -1
  const length = array.length
  while(++index<length){
    interatee(array[index],index)
  }
}

//工具函数_判断是否为引用类型
function isObject(target){
  const type = typeof target
  return target !== null && (type==='object'||type==='function')
}

//工具函数_获取实际类别
function getType(target){
  return Object.prototype.toString.call(target)
}

//工具函数_初始化被克隆的对象
function getInit(target){
  const Ctor = target.constructor
  return new Ctor()
}

//工具函数_克隆Symbol
function cloneSymbol(target){
  return Object(Symbol.prototype.valueOf.call(target))
}

//工具函数_克隆正则
function cloneReg(target){
  const reFlags = /\W*$/
  const result = new target.constructor(target.source,reFlags.exec(target))
  result.lastIndex = target.lastIndex
  return result
}

//工具函数_克隆函数
function cloneFunction(func){
  const bodyReg = /(?<={})(.|\n+(?=}))/m
  const paramsReg = /()/
}

//工具函数_克隆不可遍历类型
function cloneOtherType(target,type){
  const Ctor = target.constructor
  switch(type){
    case boolTag:
    case numbertag:
    case stringTag:
    case errorTag:
      return new Ctor(target)
    case regexTag:
      return cloneReg(target)
    case symbolTag:
      return cloneSymbol(target)
    case funcTag:
      return cloneFunction(target)
    default:
      return null
  }
}

function clone(target,map=new WeakMap()){
  if(!isObject(target)){
    return target
  }
  const type = getType(target)
  let cloneTarget;
  if(deepTag.includes(type)){
    cloneTarget = getInit(target,type)
  }else{
    return cloneOtherType(target,type)
  }
  
  if(map.get(target)){
    return target
  }
  map.set(target,cloneTarget)

  //处理map和set
  if(type === setTag){
    target.forEach(value=>{
      cloneTarget.add(clone(value))
    })
    return cloneTarget
  }

  if(type === mapTag){
    target.forEach((value,key)=>{
      clone.set(key,clone(value))
    })
    return cloneTarget
  }

  const keys = type === arrayTag?undefined:Object.keys(target)
  forEach(keys||target,(value,key)=>{// key和idx
    if(keys){
      key = value
    }
    cloneTarget[key] = clone(target[key],map)
  })
  return cloneTarget
}



